
Artículo científico
Datos
- Datos tomados del artículo referenciado previamente.
- Fuente de datos - Artículo en PLOS | ONE.
- En la base de datos se tienen dos grupos bajo análisis:
- Grupo Long jumpers: id 1 a 23.
- Grupo untrained men: id 24-45.
Lectura de datos
library(readxl)
library(tidyverse)
datos <- read_xlsx("../data/Data_Paper_Plos_One_Muscle.xlsx", skip = 3,
na = "N/A", n_max = 47) %>%
rename(RA_takeof_leg = RA...7,
OB_takeof_leg = OB...8,
PM_takeof_leg = PM...9,
QL_takeof_leg = QL...10,
ES_takeof_leg = ES...11,
Gmax_takeof_leg = Gmax...12,
Gmed_takeof_leg = Gmed...13,
IL_takeof_leg = IL...14,
RA_free_leg = RA...15,
OB_free_leg = OB...16,
PM_free_leg = PM...17,
QL_free_leg = QL...18,
ES_free_leg = ES...19,
Gmax_free_leg = Gmax...20,
Gmed_free_leg = Gmed...21,
IL_free_leg = IL...22,
id = ID,
edad = `Age (years)`,
altura_cm = `Height (cm)`,
imc = `Body mass (kg)`,
dist_salto_cm = `long jump distance (cm)`,
sprint_100m_seconds = `100-m sprint time (s)`,
grasa_subcut_cm2 = `Subcutaneous fat CSA (absolute value, cm2)`) %>%
mutate(type = if_else(id %in% c(1:23), true = "Long jumpers",
false = "Untrained men"))
datos
Objetivos
- Replicar análisis estadísticos aplicados en el artículo científico de interés.
- Evidenciar la relación existente entre características anatómicas de atletas vs rendimiento en salto largo.
- Evaluar otros métodos de statistical learning y compararlos con los resultados obtenidos por los autores.
Resultados adicionales con R
Distribuciones
datos %>%
select_if(is.numeric) %>%
select(-id) %>%
gather(key = "variable", value = "valor") %>%
ggplot(data = ., aes(x = valor)) +
facet_wrap(facets = ~variable, scales = "free", ncol = 4) +
geom_histogram(aes(y = ..density..), bins = 10, color = "black",
fill = "gray60") +
geom_density(fill = "gray50", alpha = 0.18) +
geom_rug() +
labs(x = "", y = "Densidad") +
theme_light() +
theme(strip.background = element_rect(fill = "deepskyblue4"),
strip.text = element_text(color = "black"))

Gráficos cuantil cuantil

Comparativos
- Se comparan registros de cross-sectional area (CSA) de la pierna de despeque (takeoff) vs la pierna libre (free). Las variables (músculos) a comparar son las siguientes:
- RA: recto abdominal.
- OB: oblicuos internos y externos.
- PM: psoas mayor.
- QL: cuadrado lumbar.
- ES: erector spinae.
- Gmax: gluteo mayor.
- Gmed: gluteos medio y mínimo.
- IL: iliaco
df_takeoff_leg <- datos %>%
select(RA_takeof_leg:IL_takeof_leg) %>%
gather(key = "variable", value = "valor") %>%
mutate(tipo = "TakeoffLeg")
df_free_leg <- datos %>%
select(RA_free_leg:IL_free_leg) %>%
gather(key = "variable", value = "valor") %>%
mutate(tipo = "FreeLeg")
df_takeoff_free <- df_takeoff_leg %>%
bind_rows(df_free_leg)
df_takeoff_free %>%
separate(col = variable, into = c("variable", "v1", "v2")) %>%
select(-c(v1, v2)) %>%
ggplot(data = ., aes(x = tipo, y = valor, fill = tipo)) +
facet_wrap(facets = ~variable, scales = "free", ncol = 4) +
geom_boxplot(color = "black") +
scale_fill_manual(values = c("darkgreen", "gold4")) +
labs(x = "Tipo de pierna", y = "") +
theme_light() +
theme(strip.background = element_rect(fill = "deepskyblue4"),
strip.text = element_text(color = "black"),
legend.position = "none")

Shapiro Wilk
Se comprueba la normalidad de las variables (\(\alpha = 0.05\)), bajo el siguiente juego de hipótesis:
\[H_0: X \sim N(\mu, \sigma^2)\\
H1: x \nsim N(\mu, \sigma^2)\]
- Nota: aunque los autores mencionan que fueron aplicadas las pruebas de Shapiro Wilk para comprobar el supuesto de normalidad, en la tabla anterior se evidencia que algunas variables (ej. distancia de salto, grasa subcutanea, entre otras) no se distribuyen de forma normal. Este resultado tiene connotaciones de importancia, ya que las correlaciones podrían ser obtenidas mediante métodos no paramétricos.
Matriz de correlaciones
- Se construye la matriz de correlaciones (método de Pearson).
- La variable que presente mayor correlación lineal con la longitud del salto, será tenida en cuenta para estructurar el modelo de regresión lineal simple (RLS). Con las demás variables se construye el modelo de regresión lineal múltiple (RLM).

- Notas:
- Se evidencia alta correlación entre algunas variables. Este patrón sugiere problemas de multicolinealidad al ajustar un modelo de RLM.
- Atletas con mayor altura tienden a presentar saltos de menor distancia. Este comportamiento es obtenido de igual forma en aquellos que aumentan la velocidad del sprint al saltar, es decir, que a mayor velocidad, menor longitud de salto.
- Atletas con el músculo recto abdominal de mayor longitud, presentan mayores distancias en sus saltos. Con esta variable se ajusta el modelo de RLS.
Regresión Lineal Simple (RLS)
- Se propone cuantificar la unidad de cambio en la distancia del salto vs la longitud (cm2/kg2/3) del músculo recto abdominal (RA), para la pierna de despegue (takeoff).
- El modelo de RLS puede ser expresado de la siguiente manera: \[Y = \beta_0\ + \beta_1X \\
\hat{Y} = \hat{\beta_0}\ + \hat{\beta_1}X\ + \epsilon\]
- Escrito de cara al fenómeno bajo estudio, el modelo queda expresado como sigue: \[Distancia = \hat{\beta_0}\ + (\hat{\beta_1}\times RA) + \epsilon\]
- Este modelo de RLS es ajustado a través del Método de Mínimos Cuadrados.
Modelo Lineal con lm()
Call:
lm(formula = dist_salto_cm ~ RA_takeof_leg, data = datos)
Residuals:
Min 1Q Median 3Q Max
-72.26 -22.41 8.38 22.24 65.10
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 589.584 49.894 11.817 9.66e-11 ***
RA_takeof_leg 11.928 4.443 2.685 0.0139 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 40.89 on 21 degrees of freedom
(22 observations deleted due to missingness)
Multiple R-squared: 0.2555, Adjusted R-squared: 0.2201
F-statistic: 7.208 on 1 and 21 DF, p-value: 0.01387
- Nota: el resultado anterior sugiere que la variable
RA_takeof_leg es estadísticamente significativa (\(valor\ p =0.0139\)) sobre la variabilidad observada en la distancia del salto. Además, se puede inferir que por cada unidad que aumenta RA_takeof_leg, la distancia de salto es 11.928 centímetros mayor. La variable RA_takeof_leg explica 22.01% de la variabilidad observada en la distancia de salto.
Significancia Estadística
Analysis of Variance Table
Response: dist_salto_cm
Df Sum Sq Mean Sq F value Pr(>F)
RA_takeof_leg 1 12050 12050.0 7.2078 0.01387 *
Residuals 21 35108 1671.8
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residuales

- Normalidad (Shapiro Wilk) de los residuales:
Shapiro-Wilk normality test
data: residuals(mod_rls)
W = 0.96191, p-value = 0.5029
studentized Breusch-Pagan test
data: mod_rls
BP = 0.0025838, df = 1, p-value = 0.9595
Durbin-Watson test
data: mod_rls
DW = 2.1677, p-value = 0.7123
alternative hypothesis: true autocorrelation is greater than 0
- Se comprueba que existe normalidad de los residuos, son homocedasticos y no existe autocorrelación de los mismos.
Reales vs Predichos

- La correlación entre los valores reales y valores predichos por el modelo de RLS es: 0.505; más baja que la reportada por los autores al ajustar un modelo de RLM, cuyo valor es igual a 0.892
Regresión Lineal Múltiple (RLM)
- Para la construcción del modelo de RLM se comprueba la multicolinealidad de las variables y se proponen cuatro alternativas:
- Modelo 0: modelo con todas las variables incluidas como predictoras.
- Modelo 1: Modelo de RLM con eliminación de variables por valores de correlación y factor inflacionario de varianza - VIF..
- Modelo 2: Modelo de RLM con eliminación de variables por VIF a través del métodos Stepwise (utilizado por los autores del artículo).
- Modelo 3: Modelo de regresión por componentes principales (mínimos cuadrados parciales).
- Los modelos son comparados a través del R2 ajustado (mayor mejor) y el cuadrado medio del error (CME).
Modelo 0
Call:
lm(formula = dist_salto_cm ~ ., data = datos %>% select_if(is.numeric) %>%
select(-id))
Residuals:
1 2 3 4 5 6 7 8 9
-0.24001 -1.43196 -0.91660 -0.75285 -0.04370 1.48290 -0.44264 1.69525 -0.39388
10 11 12 13 14 15 16 17 18
1.11512 -1.41008 0.27780 -0.83303 -0.28836 1.11155 -0.39267 0.08616 1.18270
19 20 21 22 23
0.62738 -0.80017 1.33190 -1.93656 0.97174
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1266.6968 182.3241 6.948 0.0910 .
edad -23.4171 3.4665 -6.755 0.0936 .
altura_cm 6.1246 1.3465 4.549 0.1378
imc -2.7528 1.3980 -1.969 0.2992
sprint_100m_seconds -92.8684 5.1288 -18.107 0.0351 *
RA_takeof_leg 124.1035 12.0047 10.338 0.0614 .
OB_takeof_leg 7.1425 2.1907 3.260 0.1895
PM_takeof_leg 9.0525 2.7581 3.282 0.1883
QL_takeof_leg 7.8868 1.4157 5.571 0.1131
ES_takeof_leg 35.5716 5.3988 6.589 0.0959 .
Gmax_takeof_leg -1.0174 0.8984 -1.132 0.4605
Gmed_takeof_leg -10.5371 0.9414 -11.193 0.0567 .
IL_takeof_leg -0.4193 2.4356 -0.172 0.8915
RA_free_leg -86.7869 9.1217 -9.514 0.0667 .
OB_free_leg -2.4849 1.2159 -2.044 0.2897
PM_free_leg -17.9138 3.3439 -5.357 0.1175
QL_free_leg -7.7265 3.9823 -1.940 0.3030
ES_free_leg -49.2399 6.2703 -7.853 0.0806 .
Gmax_free_leg 2.4543 0.5668 4.330 0.1445
Gmed_free_leg 12.7940 0.9606 13.319 0.0477 *
IL_free_leg 2.8488 2.3869 1.194 0.4440
grasa_subcut_cm2 -2.3272 0.3648 -6.379 0.0990 .
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 4.83 on 1 degrees of freedom
(22 observations deleted due to missingness)
Multiple R-squared: 0.9995, Adjusted R-squared: 0.9891
F-statistic: 96.23 on 21 and 1 DF, p-value: 0.08023
- El R2 ajustado es próximo a 1, sin embargo, pocas variables independientes (predictoras) son estadísticamente significativas (\(p<0.05\)), patron de comportamiento que sugiere problemas de multicolinealidad. La siguiente gráfica muestra anomalías en los residuales del modelo.

- Estos resultados evidencian que el modelo ajustado no es adecuado para explicar la variabilidad observada en la distancia de salto. Es importante resaltar que el R2 no es la mejor medida de bondad de ajuste, ya que éste aumenta en función del número de predictores.
Modelo 1
- Selección de predictores teniendo en cuenta valores iguales o inferiores a 0.70 de correlación. La selección es posible hacerla con la bibliteca
usdm que posee funciones flexibles para diagnósticos de multicolinealidad.
10 variables from the 21 input variables have collinearity problem:
ES_free_leg RA_takeof_leg OB_takeof_leg PM_takeof_leg Gmed_takeof_leg imc Gmax_free_leg Gmax_takeof_leg ES_takeof_leg QL_free_leg
After excluding the collinear variables, the linear correlation coefficients ranges between:
min correlation ( OB_free_leg ~ sprint_100m_seconds ): -0.001734317
max correlation ( IL_free_leg ~ IL_takeof_leg ): 0.6817036
---------- VIFs of the remained variables --------
Este resultado muestra que de las 21 variables consideradas en el modelo inicial (modelo 0) 10 de ellas presentan problemas de colinealidad. Tomando un límite de 0.70 de correlación como criterio de exclusión de predictores, la correlación máxima presente en las variables seleccionadas, es de 0.68. La tabla anterior muestra los predictores que podrían hacer parte del modelo.
Nuevo modelo:
Call:
lm(formula = dist_salto_cm ~ edad + altura_cm + sprint_100m_seconds +
QL_takeof_leg + IL_takeof_leg + RA_free_leg + OB_free_leg +
PM_free_leg + Gmed_free_leg + IL_free_leg + grasa_subcut_cm2,
data = datos)
Residuals:
Min 1Q Median 3Q Max
-39.024 -13.760 -0.812 13.552 38.971
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1859.2274 339.7523 5.472 0.000194 ***
edad 4.8879 5.8586 0.834 0.421854
altura_cm -3.8708 1.5704 -2.465 0.031409 *
sprint_100m_seconds -58.9174 20.8987 -2.819 0.016692 *
QL_takeof_leg -2.5243 5.5584 -0.454 0.658553
IL_takeof_leg 10.7345 6.0471 1.775 0.103514
RA_free_leg 6.0558 5.5662 1.088 0.299875
OB_free_leg -0.4214 2.0322 -0.207 0.839505
PM_free_leg -0.1120 3.1732 -0.035 0.972481
Gmed_free_leg -0.6212 1.5826 -0.393 0.702176
IL_free_leg -4.6031 6.7318 -0.684 0.508261
grasa_subcut_cm2 0.4789 0.8361 0.573 0.578311
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 29.51 on 11 degrees of freedom
(22 observations deleted due to missingness)
Multiple R-squared: 0.7968, Adjusted R-squared: 0.5936
F-statistic: 3.921 on 11 and 11 DF, p-value: 0.01622
- El R2 ajustado es igual a 0.5936 y sólo son estadísticamente significativas las variables altura y sprint. En general, el modelo es estadísticamente significativo (\(p = 0.01622\)) para explicar la variabilidad en la distancia de salto.
Modelo 2
Modelo 3
Modelo 4
LS0tDQp0aXRsZTogIkFuw6FsaXNpcyBkZSBSZWdyZXNpw7NuIGNvbiBSIg0Kc3VidGl0bGU6ICJDb21wYXJhY2nDs24gZGUgbW9kZWxvcyBkZSByZWdyZXNpw7NuIGNvbiBSIg0KYXV0aG9yOiAiRWRpbWVyIERhdmlkIEphcmFtaWxsbyINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICBjc3M6IGNzcy9lc3RpbG8uY3NzDQogICAgdGhlbWU6IGNvc21vDQogICAgaGlnaGxpZ2h0OiB6ZW5idXJuDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGVycm9yID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiLA0KICAgICAgICAgICAgICAgICAgICAgIGZpZy53aWR0aCA9IDguNSwNCiAgICAgICAgICAgICAgICAgICAgICBmaWcuaGVpZ2h0ID0gNSkNCmBgYA0KDQo8aW1nIHNyYz0iaW1nL3NjaWVuY2UucG5nIiBzdHlsZT0icG9zaXRpb246YWJzb2x1dGU7dG9wOjBweDtyaWdodDozMHB4OyB3aWR0aDoxNTBweCIgLz4NCg0KIyBBcnTDrWN1bG8gY2llbnTDrWZpY28NCg0KPGNlbnRlcj4NCjxpbWcgc3JjID0gImltZy9wYXBlci5wbmciIC8+DQo8L2NlbnRlcj4NCg0KIyBEYXRvcw0KDQotIERhdG9zIHRvbWFkb3MgZGVsIGFydMOtY3VsbyByZWZlcmVuY2lhZG8gcHJldmlhbWVudGUuDQotIFtGdWVudGUgZGUgZGF0b3MgLSBBcnTDrWN1bG8gZW4gUExPUyB8IE9ORS5dKGh0dHBzOi8vam91cm5hbHMucGxvcy5vcmcvcGxvc29uZS9hcnRpY2xlP2lkPTEwLjEzNzEvam91cm5hbC5wb25lLjAyMjU0MTMjcG9uZS0wMjI1NDEzLWcwMDEpDQotIEVuIGxhIGJhc2UgZGUgZGF0b3Mgc2UgdGllbmVuIGRvcyBncnVwb3MgYmFqbyBhbsOhbGlzaXM6DQogICAgLSAqKkdydXBvICpMb25nIGp1bXBlcnMqOioqIGlkIDEgYSAyMy4NCiAgICAtICoqR3J1cG8gKnVudHJhaW5lZCBtZW4qOioqIGlkIDI0LTQ1Lg0KDQojIExlY3R1cmEgZGUgZGF0b3MNCg0KYGBge3J9DQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KZGF0b3MgPC0gcmVhZF94bHN4KCIuLi9kYXRhL0RhdGFfUGFwZXJfUGxvc19PbmVfTXVzY2xlLnhsc3giLCBza2lwID0gMywNCiAgICAgICAgICAgICAgICAgICBuYSA9ICJOL0EiLCBuX21heCA9IDQ3KSAlPiUgDQogIHJlbmFtZShSQV90YWtlb2ZfbGVnID0gUkEuLi43LA0KICAgICAgICAgT0JfdGFrZW9mX2xlZyA9IE9CLi4uOCwNCiAgICAgICAgIFBNX3Rha2VvZl9sZWcgPSBQTS4uLjksDQogICAgICAgICBRTF90YWtlb2ZfbGVnID0gUUwuLi4xMCwNCiAgICAgICAgIEVTX3Rha2VvZl9sZWcgPSBFUy4uLjExLA0KICAgICAgICAgR21heF90YWtlb2ZfbGVnID0gR21heC4uLjEyLA0KICAgICAgICAgR21lZF90YWtlb2ZfbGVnID0gR21lZC4uLjEzLA0KICAgICAgICAgSUxfdGFrZW9mX2xlZyA9IElMLi4uMTQsDQogICAgICAgICBSQV9mcmVlX2xlZyA9IFJBLi4uMTUsDQogICAgICAgICBPQl9mcmVlX2xlZyA9IE9CLi4uMTYsDQogICAgICAgICBQTV9mcmVlX2xlZyA9IFBNLi4uMTcsDQogICAgICAgICBRTF9mcmVlX2xlZyA9IFFMLi4uMTgsDQogICAgICAgICBFU19mcmVlX2xlZyA9IEVTLi4uMTksDQogICAgICAgICBHbWF4X2ZyZWVfbGVnID0gR21heC4uLjIwLA0KICAgICAgICAgR21lZF9mcmVlX2xlZyA9IEdtZWQuLi4yMSwNCiAgICAgICAgIElMX2ZyZWVfbGVnID0gSUwuLi4yMiwNCiAgICAgICAgIGlkID0gSUQsDQogICAgICAgICBlZGFkID0gYEFnZSAoeWVhcnMpYCwNCiAgICAgICAgIGFsdHVyYV9jbSA9IGBIZWlnaHQgKGNtKWAsDQogICAgICAgICBpbWMgPSBgQm9keSBtYXNzIChrZylgLA0KICAgICAgICAgZGlzdF9zYWx0b19jbSA9IGBsb25nIGp1bXAgZGlzdGFuY2UgKGNtKWAsDQogICAgICAgICBzcHJpbnRfMTAwbV9zZWNvbmRzID0gYDEwMC1tIHNwcmludCB0aW1lIChzKWAsDQogICAgICAgICBncmFzYV9zdWJjdXRfY20yID0gYFN1YmN1dGFuZW91cyBmYXQgQ1NBIChhYnNvbHV0ZSB2YWx1ZSwgY20yKWApICU+JSANCiAgbXV0YXRlKHR5cGUgPSBpZl9lbHNlKGlkICVpbiUgYygxOjIzKSwgdHJ1ZSA9ICJMb25nIGp1bXBlcnMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgZmFsc2UgPSAiVW50cmFpbmVkIG1lbiIpKQ0KZGF0b3MNCmBgYA0KDQojIE9iamV0aXZvcw0KDQotIFJlcGxpY2FyIGFuw6FsaXNpcyBlc3RhZMOtc3RpY29zIGFwbGljYWRvcyBlbiBlbCBhcnTDrWN1bG8gY2llbnTDrWZpY28gZGUgaW50ZXLDqXMuDQotIEV2aWRlbmNpYXIgbGEgcmVsYWNpw7NuIGV4aXN0ZW50ZSBlbnRyZSBjYXJhY3RlcsOtc3RpY2FzIGFuYXTDs21pY2FzIGRlIGF0bGV0YXMgdnMgcmVuZGltaWVudG8gZW4gc2FsdG8gbGFyZ28uDQotIEV2YWx1YXIgb3Ryb3MgbcOpdG9kb3MgZGUgWypzdGF0aXN0aWNhbCBsZWFybmluZypdKGh0dHBzOi8vZWRpbWVyLmdpdGh1Yi5pby9kb2N1bWVudHNfUi9MaW5lYXJNb2RlbHNfTGVhc3RTcXVhcmVzL0xpbmVhck1vZGVsc19MZWFzdFNxYXVhcmVzLmh0bWwjMSkgeSBjb21wYXJhcmxvcyBjb24gbG9zIHJlc3VsdGFkb3Mgb2J0ZW5pZG9zIHBvciBsb3MgYXV0b3Jlcy4NCg0KIyBSZXN1bHRhZG9zIGRlbCAqcGFwZXIqIA0KDQojIyBDb3JyZWxhY2lvbmVzIA0KDQotIEF1bnF1ZSBmdWVyb24gbnVtZXJvc29zIGxvcyByZXN1bHRhZG9zIG9idGVuaWRvcyBwb3IgbG9zIGF1dG9yZXMsIHBhcmEgZWwgb2JqZXRpdm8gZGUgZXN0ZSBkb2N1bWVudG8gc2UgZGVzdGFjYW4gbG9zIHNpZ3VpZW50ZXM6DQogICAgLSBMYSByZWxhY2nDs24gZW50cmUgZWwgw6FyZWEgdHJhbnN2ZXJzYWwgcmVsYXRpdmEgKENTQSkgZGVsIHJlY3RvIGFiZG9taW5hbCAoQVIpIGRlbCBsYWRvIGRlIGxhIHBpZXJuYSBkZSBkZXNwZWd1ZSB5IGVsIG1lam9yIHJlZ2lzdHJvIHBlcnNvbmFsIHBhcmEgZWwgc2FsdG8gbGFyZ28uDQogICAgICAgIC0gKipDb3JyZWxhY2nDs246KiogMC42NzQNCiAgICAgICAgLSAqKlZhbG9yIHA6KiogMC4wMDQgKGVzdGFkw61zdGljYW1lbnRlIHNpZ25pZmljYXRpdm8pDQoNCi0gTGFzIGNvcnJlbGFjaW9uZXMgKGNvbiBpbnRlcnZhbG8gZGUgY29uZmlhbnphIGRlbCA5NSUpIHNlIHByZXNlbnRhbiBlbiBsYSBzaWd1aWVudGUgdGFibGE6DQoNCjxjZW50ZXI+DQo8aW1nIHNyYyA9ICJpbWcvY29ycmVsYXRpb25zLnBuZyIvPg0KPC9jZW50ZXI+DQoNCiMjIEdyw6FmaWNvIGRlIGRpc3BlcnNpw7NuIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQ0KDQojIyMgT3JpZ2luYWwNCg0KPGNlbnRlcj4NCjxpbWcgc3JjID0gImltZy9wYXBlcjIucG5nIiB3aWR0aD0iNDAwIiAvPg0KPC9jZW50ZXI+DQoNCiMjIyBSw6lwbGljYSBjb24gUg0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmRhdG9zICU+JSANCiAgZ2dwbG90KGRhdGEgPSAuLCBhZXMoeCA9IFJBX3Rha2VvZl9sZWcsIHkgPSBkaXN0X3NhbHRvX2NtKSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAzKSArDQogIGxhYnMoeCA9IGV4cHJlc3Npb24oJ1JlbGF0aXZlIENTQSBvZiBSQSB0YWtlb2ZmIGxlZyBzaWRlIC0gY20nXiIyIi8na2cnXiIyLzMiKSwNCiAgICAgICB5ID0gIlBlcnNvbmFsIGJlc3QgcmVjb3JkIG9mIGxvbmcganVtcCAoY20pIikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsdHkgPSAzLCBsd2QgPSAxLCBjb2xvciA9ICJibGFjayIpICsNCiAgdGhlbWVfbGlnaHQoKQ0KYGBgDQoNCiMjIFByZWRpY2hvcyB2cyBSZWFsZXMgKCpwYXBlciopDQoNCjxjZW50ZXI+DQo8aW1nIHNyYyA9ICJpbWcvcGFwZXIzLnBuZyIgd2lkdGg9IjQwMCIgLz4NCjwvY2VudGVyPg0KDQojIFJlc3VsdGFkb3MgYWRpY2lvbmFsZXMgY29uIFINCg0KIyMgRGlzdHJpYnVjaW9uZXMNCg0KYGBge3IsIGZpZy5oZWlnaHQ9MTB9DQpkYXRvcyAlPiUgDQogIHNlbGVjdF9pZihpcy5udW1lcmljKSAlPiUgDQogIHNlbGVjdCgtaWQpICU+JSANCiAgZ2F0aGVyKGtleSA9ICJ2YXJpYWJsZSIsIHZhbHVlID0gInZhbG9yIikgJT4lIA0KICBnZ3Bsb3QoZGF0YSA9IC4sIGFlcyh4ID0gdmFsb3IpKSArDQogIGZhY2V0X3dyYXAoZmFjZXRzID0gfnZhcmlhYmxlLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSA0KSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLCBiaW5zID0gMTAsIGNvbG9yID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICAgIGZpbGwgPSAiZ3JheTYwIikgKw0KICBnZW9tX2RlbnNpdHkoZmlsbCA9ICJncmF5NTAiLCBhbHBoYSA9IDAuMTgpICsNCiAgZ2VvbV9ydWcoKSArDQogIGxhYnMoeCA9ICIiLCB5ID0gIkRlbnNpZGFkIikgKw0KICB0aGVtZV9saWdodCgpICsNCiAgdGhlbWUoc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImRlZXBza3libHVlNCIpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIikpDQpgYGANCg0KIyMgR3LDoWZpY29zIGN1YW50aWwgY3VhbnRpbA0KDQpgYGB7ciwgZmlnLmhlaWdodD0xMH0NCmxpYnJhcnkocXFwbG90cikNCmRhdG9zICU+JSANCiAgc2VsZWN0X2lmKGlzLm51bWVyaWMpICU+JSANCiAgc2VsZWN0KC1pZCkgJT4lIA0KICBnYXRoZXIoa2V5ID0gInZhcmlhYmxlIiwgdmFsdWUgPSAidmFsb3IiKSAlPiUgDQogIGdncGxvdChkYXRhID0gLiwgYWVzKHNhbXBsZSA9IHZhbG9yKSkgKw0KICBmYWNldF93cmFwKGZhY2V0cyA9IH52YXJpYWJsZSwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gNCkgKw0KICBnZW9tX3FxX2JhbmQoZmlsbCA9ICJncmF5MjUiKSArDQogIHN0YXRfcXFfbGluZShjb2xvciA9ICJkYXJrZ3JlZW4iKSArDQogIHN0YXRfcXFfcG9pbnQoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC44KSArDQogIGxhYnMoeCA9ICJDdWFudGlsZXMgdGXDs3JpY29zIiwgeSA9ICJDdWFudGlsZXMgbXVlc3RyYWxlcyIpICsNCiAgdGhlbWVfbGlnaHQoKSArDQogIHRoZW1lKHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJkZWVwc2t5Ymx1ZTQiKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpKQ0KYGBgDQoNCiMjIENvbXBhcmF0aXZvcw0KDQotIFNlIGNvbXBhcmFuIHJlZ2lzdHJvcyAgZGUgKmNyb3NzLXNlY3Rpb25hbCBhcmVhIChDU0EpKiBkZSBsYSBwaWVybmEgZGUgZGVzcGVxdWUgKCp0YWtlb2ZmKikgdnMgbGEgcGllcm5hIGxpYnJlICgqZnJlZSopLiBMYXMgdmFyaWFibGVzIChtw7pzY3Vsb3MpIGEgY29tcGFyYXIgc29uIGxhcyBzaWd1aWVudGVzOg0KICAgIC0gKipSQToqKiByZWN0byBhYmRvbWluYWwuDQogICAgLSAqKk9COioqIG9ibGljdW9zIGludGVybm9zIHkgZXh0ZXJub3MuDQogICAgLSAqKlBNOioqIHBzb2FzIG1heW9yLg0KICAgIC0gKipRTDoqKiBjdWFkcmFkbyBsdW1iYXIuDQogICAgLSAqKkVTOioqIGVyZWN0b3IgKnNwaW5hZSouDQogICAgLSAqKkdtYXg6KiogZ2x1dGVvIG1heW9yLg0KICAgIC0gKipHbWVkOioqIGdsdXRlb3MgbWVkaW8geSBtw61uaW1vLg0KICAgIC0gKipJTDoqKiBpbGlhY28NCg0KYGBge3IsIGZpZy5oZWlnaHQ9NS41fQ0KZGZfdGFrZW9mZl9sZWcgPC0gZGF0b3MgJT4lIA0KICBzZWxlY3QoUkFfdGFrZW9mX2xlZzpJTF90YWtlb2ZfbGVnKSAlPiUgDQogIGdhdGhlcihrZXkgPSAidmFyaWFibGUiLCB2YWx1ZSA9ICJ2YWxvciIpICU+JSANCiAgbXV0YXRlKHRpcG8gPSAiVGFrZW9mZkxlZyIpDQoNCmRmX2ZyZWVfbGVnIDwtIGRhdG9zICU+JSANCiAgc2VsZWN0KFJBX2ZyZWVfbGVnOklMX2ZyZWVfbGVnKSAlPiUgDQogIGdhdGhlcihrZXkgPSAidmFyaWFibGUiLCB2YWx1ZSA9ICJ2YWxvciIpICU+JSANCiAgbXV0YXRlKHRpcG8gPSAiRnJlZUxlZyIpDQoNCmRmX3Rha2VvZmZfZnJlZSA8LSBkZl90YWtlb2ZmX2xlZyAlPiUgDQogIGJpbmRfcm93cyhkZl9mcmVlX2xlZykNCg0KZGZfdGFrZW9mZl9mcmVlICU+JSANCiAgc2VwYXJhdGUoY29sID0gdmFyaWFibGUsIGludG8gPSBjKCJ2YXJpYWJsZSIsICJ2MSIsICJ2MiIpKSAlPiUgDQogIHNlbGVjdCgtYyh2MSwgdjIpKSAgJT4lIA0KICBnZ3Bsb3QoZGF0YSA9IC4sIGFlcyh4ID0gdGlwbywgeSA9IHZhbG9yLCBmaWxsID0gdGlwbykpICsNCiAgZmFjZXRfd3JhcChmYWNldHMgPSB+dmFyaWFibGUsIHNjYWxlcyA9ICJmcmVlIiwgbmNvbCA9IDQpICsNCiAgZ2VvbV9ib3hwbG90KGNvbG9yID0gImJsYWNrIikgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJkYXJrZ3JlZW4iLCAiZ29sZDQiKSkgKw0KICBsYWJzKHggPSAiVGlwbyBkZSBwaWVybmEiLCB5ID0gIiIpICsNCiAgdGhlbWVfbGlnaHQoKSArDQogIHRoZW1lKHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJkZWVwc2t5Ymx1ZTQiKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpgYGANCg0KIyMgU2hhcGlybyBXaWxrDQoNClNlIGNvbXBydWViYSBsYSBub3JtYWxpZGFkIGRlIGxhcyB2YXJpYWJsZXMgKCRcYWxwaGEgPSAwLjA1JCksIGJham8gZWwgc2lndWllbnRlIGp1ZWdvIGRlIGhpcMOzdGVzaXM6DQoNCiQkSF8wOiBYIFxzaW0gTihcbXUsIFxzaWdtYV4yKVxcDQpIMTogeCBcbnNpbSBOKFxtdSwgXHNpZ21hXjIpJCQNCg0KYGBge3J9DQpkYXRvcyAlPiUgDQogIHNlbGVjdF9pZihpcy5udW1lcmljKSAlPiUgDQogIHNlbGVjdCgtaWQpICU+JSANCiAgZ2F0aGVyKGtleSA9ICJ2YXJpYWJsZSIsIHZhbHVlID0gInZhbG9yIikgJT4lIA0KICBncm91cF9ieSh2YXJpYWJsZSkgJT4lIA0KICBzdW1tYXJpc2UodmFsb3IgPSBsaXN0KHZhbG9yKSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBncm91cF9ieSh2YXJpYWJsZSkgJT4lIA0KICBtdXRhdGUoc2hhcGlyb192YWxvclAgPSByb3VuZChzaGFwaXJvLnRlc3QodW5saXN0KHZhbG9yKSkkcC52YWx1ZSwgZGlnaXRzID0gNSksDQogICAgICAgICBSZXN1bHRhZG8gPSBpZl9lbHNlKHNoYXBpcm9fdmFsb3JQIDw9IDAuMDUsIHRydWUgPSAiTm8gbm9ybWFsaWRhZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbHNlID0gIlPDrSBub3JtYWxpZGFkIikpICAlPiUgDQogIHNlbGVjdCgtdmFsb3IpDQpgYGANCg0KLSA8dHJlZD4qKk5vdGE6Kio8L3RyZWQ+IGF1bnF1ZSBsb3MgYXV0b3JlcyBtZW5jaW9uYW4gcXVlIGZ1ZXJvbiBhcGxpY2FkYXMgbGFzIHBydWViYXMgZGUgKlNoYXBpcm8gV2lsayogcGFyYSBjb21wcm9iYXIgZWwgc3VwdWVzdG8gZGUgbm9ybWFsaWRhZCwgZW4gbGEgdGFibGEgYW50ZXJpb3Igc2UgZXZpZGVuY2lhIHF1ZSBhbGd1bmFzIHZhcmlhYmxlcyAoKmVqLiogIGRpc3RhbmNpYSBkZSBzYWx0bywgZ3Jhc2Egc3ViY3V0YW5lYSwgZW50cmUgb3RyYXMpIG5vIHNlIGRpc3RyaWJ1eWVuIGRlIGZvcm1hIG5vcm1hbC4gRXN0ZSByZXN1bHRhZG8gdGllbmUgY29ubm90YWNpb25lcyBkZSBpbXBvcnRhbmNpYSwgeWEgcXVlIGxhcyBjb3JyZWxhY2lvbmVzIHBvZHLDrWFuIHNlciBvYnRlbmlkYXMgbWVkaWFudGUgbcOpdG9kb3MgKm5vIHBhcmFtw6l0cmljb3MqLg0KICAgIA0KIyMgTWF0cml6IGRlIGNvcnJlbGFjaW9uZXMNCg0KLSBTZSBjb25zdHJ1eWUgbGEgbWF0cml6IGRlIGNvcnJlbGFjaW9uZXMgKG3DqXRvZG8gZGUgKlBlYXJzb24qKS4NCi0gTGEgdmFyaWFibGUgcXVlIHByZXNlbnRlIG1heW9yIGNvcnJlbGFjacOzbiBsaW5lYWwgY29uIGxhIGxvbmdpdHVkIGRlbCBzYWx0bywgc2Vyw6EgdGVuaWRhIGVuIGN1ZW50YSBwYXJhIGVzdHJ1Y3R1cmFyIGVsICptb2RlbG8gZGUgcmVncmVzacOzbiBsaW5lYWwgc2ltcGxlIChSTFMpKi4gQ29uIGxhcyBkZW3DoXMgdmFyaWFibGVzIHNlIGNvbnN0cnV5ZSBlbCAqbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbGluZWFsIG3Dumx0aXBsZSAoUkxNKSouDQogICAgDQpgYGB7ciwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9OH0NCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmRhdG9zICU+JSANCiAgc2VsZWN0X2lmKGlzLm51bWVyaWMpICU+JSANCiAgc2VsZWN0KC1pZCkgJT4lIA0KICBjb3IodXNlID0gImNvbXBsZXRlLm9icyIpICU+JSANCiAgY29ycnBsb3QobWV0aG9kID0gInBpZSIsDQogICAgICAgICAgIHR5cGUgPSAidXBwZXIiLA0KICAgICAgICAgICBkaWFnID0gRkFMU0UsDQogICAgICAgICAgIHRsLmNleCA9IDAuOCwNCiAgICAgICAgICAgdGwuc3J0ID0gNDUsDQogICAgICAgICAgIGFkZGdyaWQuY29sID0gImJsYWNrIiwNCiAgICAgICAgICAgb3JkZXIgPSAiaGNsdXN0IiwNCiAgICAgICAgICAgY29sID0gYnJld2VyLnBhbChuID0gMTAsIG5hbWUgPSAiU3BlY3RyYWwiKSkNCmBgYA0KICAgIA0KLSA8dHJlZD4qKk5vdGFzOioqPC90cmVkPiANCiAgICAtIFNlIGV2aWRlbmNpYSBhbHRhIGNvcnJlbGFjacOzbiBlbnRyZSBhbGd1bmFzIHZhcmlhYmxlcy4gRXN0ZSBwYXRyw7NuIHN1Z2llcmUgcHJvYmxlbWFzIGRlICptdWx0aWNvbGluZWFsaWRhZCogYWwgYWp1c3RhciB1biBtb2RlbG8gZGUgKlJMTSouDQogICAgLSBBdGxldGFzIGNvbiBtYXlvciBhbHR1cmEgdGllbmRlbiBhIHByZXNlbnRhciBzYWx0b3MgZGUgbWVub3IgZGlzdGFuY2lhLiBFc3RlIGNvbXBvcnRhbWllbnRvIGVzIG9idGVuaWRvIGRlIGlndWFsIGZvcm1hIGVuIGFxdWVsbG9zIHF1ZSBhdW1lbnRhbiBsYSB2ZWxvY2lkYWQgZGVsICpzcHJpbnQqIGFsIHNhbHRhciwgZXMgZGVjaXIsIHF1ZSBhIG1heW9yIHZlbG9jaWRhZCwgbWVub3IgbG9uZ2l0dWQgZGUgc2FsdG8uDQogICAgLSBBdGxldGFzIGNvbiBlbCBtw7pzY3VsbyByZWN0byBhYmRvbWluYWwgZGUgbWF5b3IgbG9uZ2l0dWQsIHByZXNlbnRhbiBtYXlvcmVzIGRpc3RhbmNpYXMgZW4gc3VzIHNhbHRvcy4gQ29uIGVzdGEgdmFyaWFibGUgc2UgYWp1c3RhIGVsIG1vZGVsbyBkZSAqUkxTKi4NCiAgICANCiMgUmVncmVzacOzbiBMaW5lYWwgU2ltcGxlIChSTFMpIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQ0KDQotIFNlIHByb3BvbmUgY3VhbnRpZmljYXIgbGEgdW5pZGFkIGRlIGNhbWJpbyBlbiBsYSBkaXN0YW5jaWEgZGVsIHNhbHRvIHZzIGxhIGxvbmdpdHVkIChjbV4yXi9rZ14yLzNeKSBkZWwgbcO6c2N1bG8gcmVjdG8gYWJkb21pbmFsIChSQSksIHBhcmEgbGEgcGllcm5hIGRlIGRlc3BlZ3VlICgqdGFrZW9mZiopLg0KLSBFbCBtb2RlbG8gZGUgKlJMUyogcHVlZGUgc2VyIGV4cHJlc2FkbyBkZSBsYSBzaWd1aWVudGUgbWFuZXJhOg0KJCRZID0gXGJldGFfMFwgKyBcYmV0YV8xWCBcXA0KXGhhdHtZfSA9IFxoYXR7XGJldGFfMH1cICsgXGhhdHtcYmV0YV8xfVhcICsgXGVwc2lsb24kJA0KLSBFc2NyaXRvIGRlIGNhcmEgYWwgZmVuw7NtZW5vIGJham8gZXN0dWRpbywgZWwgbW9kZWxvIHF1ZWRhIGV4cHJlc2FkbyBjb21vIHNpZ3VlOg0KJCREaXN0YW5jaWEgPSBcaGF0e1xiZXRhXzB9XCArIChcaGF0e1xiZXRhXzF9XHRpbWVzIFJBKSArIFxlcHNpbG9uJCQNCi0gRXN0ZSBtb2RlbG8gZGUgKlJMUyogZXMgYWp1c3RhZG8gYSB0cmF2w6lzIGRlbCBbKk3DqXRvZG8gZGUgTcOtbmltb3MgQ3VhZHJhZG9zLipdKGh0dHBzOi8vZWRpbWVyLmdpdGh1Yi5pby9kb2N1bWVudHNfUi9MaW5lYXJNb2RlbHNfTGVhc3RTcXVhcmVzL0xpbmVhck1vZGVsc19MZWFzdFNxYXVhcmVzLmh0bWwjMSkNCg0KIyMgTW9kZWxvIExpbmVhbCBjb24gYGxtKClgDQoNCmBgYHtyfQ0KbW9kX3JscyA8LSBsbShkaXN0X3NhbHRvX2NtIH4gUkFfdGFrZW9mX2xlZywgZGF0YSA9IGRhdG9zKQ0Kc3VtbWFyeShtb2RfcmxzKQ0KYGBgDQoNCi0gPHRyZWQ+KipOb3RhOioqPC90cmVkPiBlbCByZXN1bHRhZG8gYW50ZXJpb3Igc3VnaWVyZSBxdWUgbGEgdmFyaWFibGUgYFJBX3Rha2VvZl9sZWdgIGVzIGVzdGFkw61zdGljYW1lbnRlIHNpZ25pZmljYXRpdmEgKCR2YWxvclwgcCA9MC4wMTM5JCkgc29icmUgbGEgdmFyaWFiaWxpZGFkIG9ic2VydmFkYSBlbiBsYSBkaXN0YW5jaWEgZGVsIHNhbHRvLiBBZGVtw6FzLCBzZSBwdWVkZSBpbmZlcmlyIHF1ZSBwb3IgY2FkYSB1bmlkYWQgcXVlIGF1bWVudGEgYFJBX3Rha2VvZl9sZWdgLCBsYSBkaXN0YW5jaWEgZGUgc2FsdG8gZXMgMTEuOTI4IGNlbnTDrW1ldHJvcyBtYXlvci4gTGEgdmFyaWFibGUgYFJBX3Rha2VvZl9sZWdgIGV4cGxpY2EgMjIuMDElIGRlIGxhIHZhcmlhYmlsaWRhZCBvYnNlcnZhZGEgZW4gbGEgZGlzdGFuY2lhIGRlIHNhbHRvLg0KDQojIyBTaWduaWZpY2FuY2lhIEVzdGFkw61zdGljYQ0KDQpgYGB7cn0NCmFub3ZhKG1vZF9ybHMpDQpgYGANCg0KIyMgUmVzaWR1YWxlcw0KDQpgYGB7cn0NCnBhcihtZnJvdyA9IGMoMiwgMikpDQpwbG90KG1vZF9ybHMpDQpgYGANCg0KLSAqKk5vcm1hbGlkYWQgKFNoYXBpcm8gV2lsaykgZGUgbG9zIHJlc2lkdWFsZXM6KiogDQoNCmBgYHtyfQ0Kc2hhcGlyby50ZXN0KHJlc2lkdWFscyhtb2RfcmxzKSkNCmBgYA0KDQotICoqSGV0ZXJvY2VkYXN0aWNpZGFkIC0gWypCcmV1c2NoIFBhZ2FuIFRlc3QqXShodHRwczovL2VzLndpa2lwZWRpYS5vcmcvd2lraS9UZXN0X2RlX0JyZXVzY2gtUGFnYW4pOioqDQoNCmBgYHtyfQ0KbGlicmFyeShsbXRlc3QpDQpicHRlc3QobW9kX3JscykNCmBgYA0KDQotICoqQXV0b2NvcnJlbGFjacOzbiAtICpbVGVzdCBkZSBEdXJiaSBXYXRzb25dKGh0dHBzOi8vZXMud2lraXBlZGlhLm9yZy93aWtpL0VzdGFkJUMzJUFEc3RpY29fZGVfRHVyYmluLVdhdHNvbikqOioqDQoNCmBgYHtyfQ0KZHd0ZXN0KG1vZF9ybHMpDQpgYGANCg0KLSBTZSBjb21wcnVlYmEgcXVlIGV4aXN0ZSBub3JtYWxpZGFkIGRlIGxvcyByZXNpZHVvcywgc29uIGhvbW9jZWRhc3RpY29zIHkgbm8gZXhpc3RlIGF1dG9jb3JyZWxhY2nDs24gZGUgbG9zIG1pc21vcy4NCg0KIyMgUmVhbGVzIHZzIFByZWRpY2hvcw0KDQpgYGB7cn0NCnJlYWxlcyA8LSBkYXRvcyRkaXN0X3NhbHRvX2NtWyFpcy5uYShkYXRvcyRkaXN0X3NhbHRvX2NtKV0NCnByZWRpY2hvc19ybHMgPC0gbW9kX3JscyRmaXR0ZWQudmFsdWVzDQpkYXRhLmZyYW1lKA0KICBSZWFsID0gcmVhbGVzLA0KICBQcmVkaWNob3MgPSBwcmVkaWNob3NfcmxzDQopICU+JSANCiAgZ2dwbG90KGRhdGEgPSAuLCBhZXMoeCA9IFByZWRpY2hvcywgeSA9IFJlYWwpKSArDQogIGdlb21fcG9pbnQoKSArDQogIGxhYnMoeCA9ICgiVmFsb3JlcyBwcmVkaWNob3MgZGUgZGlzdGFuY2lhIChjbSkiKSwNCiAgICAgICB5ID0gIlZhbG9yZXMgcmVhbGVzIGRlIGRpc3RhbmNpYSAoY20pIikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsdHkgPSAzLCBsd2QgPSAxLCBjb2xvciA9ICJibGFjayIpICsNCiAgdGhlbWVfbGlnaHQoKQ0KYGBgDQoNCi0gTGEgY29ycmVsYWNpw7NuIGVudHJlIGxvcyAqKnZhbG9yZXMgcmVhbGVzKiogeSAqKnZhbG9yZXMgcHJlZGljaG9zKiogcG9yIGVsIG1vZGVsbyBkZSAqUkxTKiBlczogYHIgcm91bmQoY29yKHJlYWxlcywgcHJlZGljaG9zX3JscyksIGRpZ2l0cyA9IDMpYDsgbcOhcyBiYWphIHF1ZSBsYSByZXBvcnRhZGEgcG9yIGxvcyBhdXRvcmVzIGFsIGFqdXN0YXIgdW4gbW9kZWxvIGRlICpSTE0qLCBjdXlvIHZhbG9yIGVzIGlndWFsIGEgMC44OTINCg0KIyBSZWdyZXNpw7NuIExpbmVhbCBNw7psdGlwbGUgKFJMTSkgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9DQoNCi0gUGFyYSBsYSBjb25zdHJ1Y2Npw7NuIGRlbCBtb2RlbG8gZGUgKlJMTSogc2UgY29tcHJ1ZWJhIGxhIG11bHRpY29saW5lYWxpZGFkIGRlIGxhcyB2YXJpYWJsZXMgeSBzZSBwcm9wb25lbiBjdWF0cm8gYWx0ZXJuYXRpdmFzOg0KICAgIC0gPHRyZWQ+KipNb2RlbG8gMDoqKjwvdHJlZD4gbW9kZWxvIGNvbiB0b2RhcyBsYXMgdmFyaWFibGVzIGluY2x1aWRhcyBjb21vIHByZWRpY3RvcmFzLg0KICAgIC0gPHRyZWQ+KipNb2RlbG8gMToqKjwvdHJlZD4gTW9kZWxvIGRlICpSTE0qIGNvbiBlbGltaW5hY2nDs24gZGUgdmFyaWFibGVzIHBvciB2YWxvcmVzIGRlIGNvcnJlbGFjacOzbiB5IFsqZmFjdG9yIGluZmxhY2lvbmFyaW8gZGUgdmFyaWFuemEgLSBWSUYuKl0oaHR0cHM6Ly9lcy53aWtpcGVkaWEub3JnL3dpa2kvRmFjdG9yX2RlX2luZmxhY2klQzMlQjNuX2RlX2xhX3ZhcmlhbnphKS4NCiAgICAtIDx0cmVkPioqTW9kZWxvIDI6Kio8L3RyZWQ+IE1vZGVsbyBkZSAqUkxNKiBjb24gZWxpbWluYWNpw7NuIGRlIHZhcmlhYmxlcyBwb3IgKlZJRiogYSB0cmF2w6lzIGRlbCBtw6l0b2RvcyAqU3RlcHdpc2UqICh1dGlsaXphZG8gcG9yIGxvcyBhdXRvcmVzIGRlbCBhcnTDrWN1bG8pLg0KICAgIC0gPHRyZWQ+KipNb2RlbG8gMzoqKjwvdHJlZD4gTW9kZWxvIGRlIHJlZ3Jlc2nDs24gcG9yIGNvbXBvbmVudGVzIHByaW5jaXBhbGVzIChbKm3DrW5pbW9zIGN1YWRyYWRvcyBwYXJjaWFsZXMqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9QYXJ0aWFsX2xlYXN0X3NxdWFyZXNfcmVncmVzc2lvbikpLg0KLSBMb3MgbW9kZWxvcyBzb24gY29tcGFyYWRvcyBhIHRyYXbDqXMgZGVsICpSXjJeIGFqdXN0YWRvKiAobWF5b3IgbWVqb3IpIHkgZWwgKmN1YWRyYWRvIG1lZGlvIGRlbCBlcnJvciAoQ01FKS4qDQoNCiMjIE1vZGVsbyAwDQoNCmBgYHtyfQ0KbW9kX3JsbTAgPC0gbG0oZGlzdF9zYWx0b19jbSB+IC4sDQogICAgICAgICAgICAgICBkYXRhID0gZGF0b3MgJT4lIHNlbGVjdF9pZihpcy5udW1lcmljKSAlPiUgc2VsZWN0KC1pZCkpDQpzdW1tYXJ5KG1vZF9ybG0wKQ0KYGBgDQoNCi0gRWwgUl4yXiBhanVzdGFkbyBlcyBwcsOzeGltbyBhIDEsIHNpbiBlbWJhcmdvLCBwb2NhcyB2YXJpYWJsZXMgaW5kZXBlbmRpZW50ZXMgKHByZWRpY3RvcmFzKSBzb24gZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2YXMgKCRwPDAuMDUkKSwgcGF0cm9uIGRlIGNvbXBvcnRhbWllbnRvIHF1ZSBzdWdpZXJlIHByb2JsZW1hcyBkZSBtdWx0aWNvbGluZWFsaWRhZC4gTGEgc2lndWllbnRlIGdyw6FmaWNhIG11ZXN0cmEgYW5vbWFsw61hcyBlbiBsb3MgcmVzaWR1YWxlcyBkZWwgbW9kZWxvLg0KDQpgYGB7cn0NCnBhcihtZnJvdyA9IGMoMiwgMikpDQpwbG90KG1vZF9ybG0wKQ0KYGBgDQoNCi0gRXN0b3MgcmVzdWx0YWRvcyBldmlkZW5jaWFuIHF1ZSBlbCBtb2RlbG8gYWp1c3RhZG8gbm8gZXMgYWRlY3VhZG8gcGFyYSBleHBsaWNhciBsYSB2YXJpYWJpbGlkYWQgb2JzZXJ2YWRhIGVuIGxhIGRpc3RhbmNpYSBkZSBzYWx0by4gRXMgaW1wb3J0YW50ZSByZXNhbHRhciBxdWUgZWwgUl4yXiBubyBlcyBsYSBtZWpvciBtZWRpZGEgZGUgYm9uZGFkIGRlIGFqdXN0ZSwgeWEgcXVlIMOpc3RlIGF1bWVudGEgZW4gZnVuY2nDs24gZGVsIG7Dum1lcm8gZGUgcHJlZGljdG9yZXMuDQoNCmBgYHtyfQ0KIyBWYWxvcmVzIHByZWRpY2hvcyBwb3IgbW9kX3JsbTANCnByZWRpY2hvc19ybG0wIDwtIG1vZF9ybG0wJGZpdHRlZC52YWx1ZXMgDQpgYGANCg0KIyMgTW9kZWxvIDENCg0KLSBTZWxlY2Npw7NuIGRlIHByZWRpY3RvcmVzIHRlbmllbmRvIGVuIGN1ZW50YSB2YWxvcmVzIGlndWFsZXMgbyBpbmZlcmlvcmVzIGEgMC43MCBkZSBjb3JyZWxhY2nDs24uIExhIHNlbGVjY2nDs24gZXMgcG9zaWJsZSBoYWNlcmxhIGNvbiBsYSBiaWJsaXRlY2EgW2B1c2RtYF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3VzZG0vdXNkbS5wZGYpIHF1ZSBwb3NlZSBmdW5jaW9uZXMgZmxleGlibGVzIHBhcmEgZGlhZ27Ds3N0aWNvcyBkZSBtdWx0aWNvbGluZWFsaWRhZC4NCg0KYGBge3J9DQojIFZhcmlhYmxlcyBwcmVkaWN0b3Jhcw0KZGZfcHJlZGljdG9yYXMgPC1kYXRvcyAlPiUNCiAgc2VsZWN0X2lmKGlzLm51bWVyaWMpICU+JSBkcGx5cjo6c2VsZWN0KC1jKGlkLCBkaXN0X3NhbHRvX2NtKSkgJT4lIA0KICBhcy5tYXRyaXgoKQ0KDQpsaWJyYXJ5KHVzZG0pDQp2aWZjb3IoeCA9IGRmX3ByZWRpY3RvcmFzLCB0aCA9IDAuNzApDQpgYGANCg0KLSBFc3RlIHJlc3VsdGFkbyBtdWVzdHJhIHF1ZSBkZSBsYXMgMjEgdmFyaWFibGVzIGNvbnNpZGVyYWRhcyBlbiBlbCBtb2RlbG8gaW5pY2lhbCAoKm1vZGVsbyAwKikgMTAgZGUgZWxsYXMgcHJlc2VudGFuIHByb2JsZW1hcyBkZSBjb2xpbmVhbGlkYWQuIFRvbWFuZG8gdW4gbMOtbWl0ZSBkZSAwLjcwIGRlIGNvcnJlbGFjacOzbiBjb21vIGNyaXRlcmlvIGRlIGV4Y2x1c2nDs24gZGUgcHJlZGljdG9yZXMsIGxhIGNvcnJlbGFjacOzbiBtw6F4aW1hIHByZXNlbnRlIGVuIGxhcyB2YXJpYWJsZXMgc2VsZWNjaW9uYWRhcywgZXMgZGUgMC42OC4gTGEgdGFibGEgYW50ZXJpb3IgbXVlc3RyYSBsb3MgcHJlZGljdG9yZXMgcXVlIHBvZHLDrWFuIGhhY2VyIHBhcnRlIGRlbCBtb2RlbG8uDQoNCi0gKipOdWV2byBtb2RlbG86KioNCg0KYGBge3J9DQptb2RfcmxtMSA8LSBsbShkaXN0X3NhbHRvX2NtIH4gZWRhZCArIGFsdHVyYV9jbSArIHNwcmludF8xMDBtX3NlY29uZHMNCiAgICAgICAgICAgICAgICsgUUxfdGFrZW9mX2xlZyArIElMX3Rha2VvZl9sZWcgKyBSQV9mcmVlX2xlZyArIE9CX2ZyZWVfbGVnDQogICAgICAgICAgICAgICArIFBNX2ZyZWVfbGVnICsgR21lZF9mcmVlX2xlZyArIElMX2ZyZWVfbGVnICsgZ3Jhc2Ffc3ViY3V0X2NtMiwNCiAgICAgICAgICAgICAgIGRhdGEgPSBkYXRvcykNCnN1bW1hcnkobW9kX3JsbTEpDQpgYGANCg0KLSBFbCBSXjJeIGFqdXN0YWRvIGVzIGlndWFsIGEgMC41OTM2IHkgc8OzbG8gc29uIGVzdGFkw61zdGljYW1lbnRlIHNpZ25pZmljYXRpdmFzIGxhcyB2YXJpYWJsZXMgYWx0dXJhIHkgc3ByaW50LiBFbiBnZW5lcmFsLCBlbCBtb2RlbG8gZXMgZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2byAoJHAgPSAwLjAxNjIyJCkgcGFyYSBleHBsaWNhciBsYSB2YXJpYWJpbGlkYWQgZW4gbGEgZGlzdGFuY2lhIGRlIHNhbHRvLiANCg0KYGBge3J9DQojIFZhbG9yZXMgcHJlZGljaG9zIHBvciBtb2RfcmxtMQ0KcHJlZGljaG9zX3JsbTEgPC0gbW9kX3JsbTEkZml0dGVkLnZhbHVlcw0KYGBgDQoNCiMjIE1vZGVsbyAyDQoNCiMjIE1vZGVsbyAzDQoNCiMjIE1vZGVsbyA0DQogICAg